/*
 * File Name:drv_led_example.c
 * Version:v1.0.0
 * Change Logs:
 * Date             Author      	main change
 * 2025-02-12      	lanxin          the first version
 *
*/

/********************************************* READ ME BEGIN *************************************************************/

/* Brief:
 *
 * *1.example for adapt mal_led.c based on rtthread.
 *
 */

/* Notice:
 *
 * *0.enable ENABLE_LED_PORT,then do adapt 1 to 5.
 *
 * *1.before operate led,should init it before.
 *
 */

/********************************************* READ ME END ***************************************************************/

/* debug define */
//#define ENABLE_LED_PORT

#ifdef ENABLE_LED_PORT

/* source file */
#include "mal_led.h"

/* adapt 1: add necessary file */
#include "rtthread.h"
#include "drv_gpio.h"

/* private define */
#define LED_TOTAL_NUM           sizeof(led_pin_msg)/sizeof(led_pin_msg[0])

#define led_gpio_msg(INDEX)     &(led_pin_msg[INDEX].gpio_msg)
#define led_enable(INDEX)       led_pin_msg[INDEX].enable
#define led_light_level(INDEX)  led_pin_msg[INDEX].light_level

/* function declaration */

/* variable declaration */
/* led light level */
enum
{
	E_LED_LIGHT_LEVEL_LOW = 0,
	E_LED_LIGHT_LEVEL_HIGH,
};

typedef struct gpio_message
{
	/* adapt 2: replace by your gpio message */
	rt_base_t   pin;//指示灯引脚
} s_gpio_msg_t;

/* 指示灯引脚信息 */
typedef struct led_pin_message
{
	s_gpio_msg_t gpio_msg;

	/* 8 bit */
	uint8_t     light_level : 1; //点亮时的电平
	uint8_t     enable      : 1; //是否使能
	uint8_t     reserve     : 6;//reserve
} s_led_pin_msg_t;

/* 指示灯实例 */
static s_led_pin_msg_t led_pin_msg[] =
{
	/* adapt 3: add your led */
	/* pin msg light light level enable state */
	{.gpio_msg.pin   = GET_PIN ( 1, 9 ), .light_level = E_LED_LIGHT_LEVEL_LOW, .enable = 1,}, //led index 0

	/* add new */
};

/* led hard operate function */
static s_led_ops_t led_ops;

/* adapt 4: realize by your gpio operate function,init read write */
static void init_led_gpio ( s_gpio_msg_t *msg )
{
	if ( msg == 0 ) return;

	rt_pin_mode ( msg->pin, PIN_MODE_OUTPUT );
}

static int read_led_gpio ( s_gpio_msg_t *msg )
{
	if ( msg == 0 ) return 0;

	return rt_pin_read ( msg->pin );
}

static void write_led_gpio ( s_gpio_msg_t *msg, uint8_t state )
{
	if ( msg == 0 ) return;

	rt_pin_write ( msg->pin, state );
}

static int _led_init ( void )
{
	for ( uint8_t i = 0; i < LED_TOTAL_NUM; i++ )
	{
		/* init led gpio */
		init_led_gpio ( led_gpio_msg ( i ) );

		/* dark led */
		write_led_gpio ( led_gpio_msg ( i ), ! ( led_light_level ( i ) ) );
	}

	return 0;
}

static int _set_single_led_state ( uint8_t index, uint8_t state )
{
	if ( index > LED_TOTAL_NUM )
		return -1;

	if ( state >= E_MAL_LED_STATE_MAX )
		return -1;

	if ( state == E_MAL_LED_DISABLE || state == E_MAL_LED_ENABLE )
	{
		led_enable ( index ) = ( state == E_MAL_LED_ENABLE ? 1 : 0 );
		return 0;
	}

	if ( !led_enable ( index ) )
	{
		return -1;
	}

	if ( E_MAL_LED_DARK == state )
	{
		write_led_gpio ( led_gpio_msg ( index ), ! ( led_light_level ( index ) ) );
	}
	else if ( E_MAL_LED_LIGHT == state )
	{
		write_led_gpio ( led_gpio_msg ( index ), led_light_level ( index ) );
	}
	else if ( E_MAL_LED_TOGGLE == state )
	{
		write_led_gpio ( led_gpio_msg ( index ), !read_led_gpio ( led_gpio_msg ( index ) ) );
	}
	else
	{
		return -1;
	}

	return 0;
}

int bsp_board_led_init ( void )
{
	led_ops.init = _led_init;
	led_ops.set_state = _set_single_led_state;

	mal_led_bind_ops ( &led_ops );

	mal_led_init();

	return 0;
}

/* adapt 5: before operate led,init it first */
INIT_BOARD_EXPORT ( bsp_board_led_init );

static int led_blink ( void )
{
	int cnt = 10;
	rt_kprintf ( "led dark\r\n" );
	MAL_LED_DARK ( 0 );
	rt_thread_mdelay ( 1000 );
	rt_kprintf ( "led light\r\n" );
	MAL_LED_LIGHT ( 0 );

	/* toggle led state */
	while ( cnt-- )
	{
		rt_kprintf ( "led toggle\r\n" );
		MAL_LED_TOGGLE ( 0 );
		rt_thread_mdelay ( 500 );
	}

	/* disable led,after this,set led state is not effective */
	rt_kprintf ( "led disable\r\n" );
	MAL_LED_DISABLE ( 0 );
	cnt = 10;

	while ( cnt-- )
	{
		rt_kprintf ( "led toggle\r\n" );
		MAL_LED_TOGGLE ( 0 );
		rt_thread_mdelay ( 500 );
	}

	/* reenable led */
	MAL_LED_ENABLE ( 0 );
	rt_kprintf ( "led enable\r\n" );
	cnt = 10;

	while ( cnt-- )
	{
		rt_kprintf ( "led toggle\r\n" );
		MAL_LED_TOGGLE ( 0 );
		rt_thread_mdelay ( 500 );
	}

	rt_kprintf ( "led dark\r\n" );
	MAL_LED_DARK ( 0 );

	return 0;
}

MSH_CMD_EXPORT ( led_blink, led_blink_test );

#endif /*ENABLE_LED_PORT*/
